package om.jenkinslog;

import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import om.Utils.EsClientUtils;
import org.apache.commons.codec.binary.StringUtils;
import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.util.EntityUtils;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.elasticsearch.action.index.IndexRequest;
import org.elasticsearch.action.search.SearchRequest;
import org.elasticsearch.action.update.UpdateAction;
import org.elasticsearch.index.query.QueryBuilders;
import org.elasticsearch.search.SearchHit;
import org.elasticsearch.search.builder.SearchSourceBuilder;

import java.io.IOException;
import java.nio.charset.StandardCharsets;
import java.text.SimpleDateFormat;
import java.util.*;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

/**
 * @author xiazhonghai
 * @date 2021/1/5 11:31
 * @description:
 */
public class JenkinsLog extends Common implements Runnable {
    ObjectMapper objectMapper = new ObjectMapper();
    static Logger logger = LogManager.getLogger(JenkinsLog.class);

    public Properties getConf() {
        return conf;
    }

    public void setConf(Properties conf) {
        this.conf = conf;
    }

    String user;
    String password;

    Properties conf;

    public String getBaseurl() {
        return baseurl;
    }

    public void setBaseurl(String baseurl) {
        this.baseurl = baseurl;
    }

    String baseurl;


    ArrayList<String> urls;

    int count = 0;

    String esindex;

    private String com;

    public String getCom() {
        return com;
    }

    public void setCom(String com) {
        this.com = com;
    }


    public List gethttpresult(String url) throws IOException {
        url += "api/json";
        HttpGet httpGet = new HttpGet(url);
        if (user != null && password == null) {
            httpGet.addHeader("Authorization", "Basic " + Base64.getEncoder().encodeToString((user + ":" + password).getBytes(StandardCharsets.UTF_8)));
        }
        CloseableHttpResponse execute = null;
        try {
            execute = httpclient.execute(httpGet);
            String data = EntityUtils.toString(execute.getEntity());
            Map httpdata = objectMapper.readValue(data, Map.class);
            if (httpdata.containsKey("jobs")) {
                List<Map> jobs = (List) httpdata.get("jobs");
                if (jobs.size() > 0) {
                    for (Map job : jobs) {
                        gethttpresult(job.get("url").toString());
                    }
                }
            } else {
                List<Map> builds = (List) httpdata.get("builds");
                if (builds.size() > 0) {
                    int count = 0;
                    for (Map build : builds) {
                        HashMap<String, Object> resultMap = new HashMap<>();
                        count++;
                        String buildurl = build.get("url").toString();

                        if (Integer.parseInt(conf.getProperty("is_need_consolelog")) == 1) {
                            Map consoleLogData = getConsoleLogData(buildurl);
                            resultMap.putAll(consoleLogData);
                        }
                        Map apiJosonData = getApiJosonData(buildurl);
                        String id = "";
                        resultMap.putAll(apiJosonData);
                        if (resultMap.get("upstreamproject") != null && !resultMap.get("upstreamproject").equals("") && resultMap.get("consoleTime") != null && !resultMap.get("consoleTime").toString().equals("")) {
                            id = resultMap.get("upstreamproject") + "-" + resultMap.get("consoleTime").toString();

                        } else {
                            id = resultMap.get("name") + "-" + resultMap.get("number");
                        }
                        resultMap.put("id", id);
                        bulkProcess.add(new IndexRequest(esindex).id(id).source(resultMap));
                    }
                }
            }

        } catch (Exception e) {
            e.printStackTrace();
        }
        return null;
    }

    public String getHttpResult(String url) {
        HttpGet httpGetbuild = new HttpGet(url);
        if (user != null && !user.equals("")) {
            httpGetbuild.addHeader("Authorization", "Basic " + Base64.getEncoder().encodeToString((user + ":" + password).getBytes(StandardCharsets.UTF_8)));
        }
        CloseableHttpResponse buildresponse = null;
        String consolelog = "";
        try {
            buildresponse = httpclient.execute(httpGetbuild);
            consolelog = EntityUtils.toString(buildresponse.getEntity());
        } catch (IOException e) {
            e.printStackTrace();
        }
        return consolelog;
    }

    public Map getApiJosonData(String url) {
        HashMap<Object, Object> resultMap = new HashMap<>();
        String apiurl = url + "api/json";
        String jsondata = getHttpResult(apiurl);
        Map map = null;
        try {
            map = objectMapper.readValue(jsondata, Map.class);
//            List actions = (List) map.get("actions");
//            Map action0 = (Map) actions.get(0);
//            List causes = (List) action0.get("causes");
//            Map cause0 = (Map) causes.get(0);
//            String upstreamProject = cause0.get("upstreamProject").toString();
//            String upProject = upstreamProject.split("-", 2)[1];
//            int index = upProject.lastIndexOf("-");
//            upProject=upProject.substring(0,index);
//            resultMap.put("upstreamproject",upProject);
            resultMap.put("duration", map.get("duration"));
            resultMap.put("id", map.get("id"));
            resultMap.put("number", map.get("number"));
            resultMap.put("result", map.get("result"));
            resultMap.put("name", map.get("fullDisplayName").toString().split("#")[0]);
            if ("SUCCESS".equals(map.get("result"))) {
                resultMap.put("success", 1);
            } else {
                resultMap.put("failed", 1);
            }
            resultMap.put("url", map.get("url"));
            Long timestamp = (Long) map.get("timestamp");
            SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss+0800");
            String created_at = simpleDateFormat.format(timestamp);
            created_at = created_at.replace(" ", "T");
            resultMap.put("created_at", created_at);
            resultMap.put("timestamp", map.get("timestamp"));
            resultMap.put("builtOn", map.get("builtOn"));
        } catch (JsonProcessingException e) {
            e.printStackTrace();
        } catch (NullPointerException e) {
            System.out.println(map);
            e.printStackTrace();
        }
        return resultMap;
    }

    public Map getConsoleLogData(String url) throws IOException {
        HashMap<Object, Object> resultMap = new HashMap<>();
        String consolelogurl = url + "consoleFull";
        String consolelog = getHttpResult(consolelogurl);
        String pattern = "Download on windows: &lt;a href=\"<a href='http://121.36.84.172.*'>";
        String finishedpatt = "Finished:.*\n";
        //获取构建状态
        Matcher finmatcher = Pattern.compile(finishedpatt).matcher(consolelog);
        String finished = "";
        //社区名称
        String org = "";
        //构建时间
        String consoleTime = "";
        if (finmatcher.find()) {
            finished = finmatcher.group(0).split(":")[1].replace("\n", "").trim();
        }
        Pattern compile = Pattern.compile(pattern);
        Matcher matcher = compile.matcher(consolelog);
//                              Download on windows: &lt;a href="<a href='http://121.36.84.172/dailybuild//openEuler-20.09/openeuler-2021-02-08-14-30-39/ISO/aarch64/openEuler-20.09-aarch64-dvd.iso'>
        if ("SUCCESS".equals(finished) && matcher.find()) {
            String urlstr = matcher.group(0);
            String namepattern = "[a-zA-Z]+-\\d+-\\d+-\\d+-\\d+-\\d+-\\d+";
            Pattern namecomplie = Pattern.compile(namepattern);
            Matcher namematcher = namecomplie.matcher(urlstr);
            if (namematcher.find()) {
                String packagename = namematcher.group(0);
//              openeuler-2021-02-08-14-30-39
                //获取名称日期
                String[] nametime = packagename.split("-", 2);
                org = nametime[0];
                consoleTime = nametime[1];
            }

            String namespace = "//[a-zA-Z]+(.*-Next|.*SP1|.*LTS|.*Mainline|.*20.09|.*)/";
            Pattern compilenamespace = Pattern.compile(namespace);
            Matcher matchernamespace = compilenamespace.matcher(urlstr);
            if (matchernamespace.find()) {
                String group = matchernamespace.group(0);
                group = group.split("//")[1].split("/")[0];
                String replace = group.replace("_", "-");
                resultMap.put("upstreamproject", replace);
            }

        }

        resultMap.put("org", org);
        resultMap.put("consoleTime", consoleTime);
        return resultMap;
    }

    public void updateTotal() throws IOException {
        esindex = properties.getProperty(com + "_esindex");
        SearchSourceBuilder searchSourceBuilder = new SearchSourceBuilder();
        searchSourceBuilder.query(QueryBuilders.matchAllQuery());
        SearchRequest searchRequest = new SearchRequest(esindex);
        searchRequest.source(searchSourceBuilder);
        HashMap<String, Map<String, Integer>> totalcountmap = new HashMap<>();
        //todo 一次获取所有数据进行计算一次，应划分批次进行累计统计
        List<SearchHit> searchHits = EsClientUtils.scrollSearchAll(esClient, 100L, searchRequest);
        for (SearchHit searchHit : searchHits) {
            Map<String, Object> sourceAsMap = searchHit.getSourceAsMap();
            String upstreamproject;
            try {
                upstreamproject = sourceAsMap.get("upstreamproject") + "";
                if (upstreamproject == null || upstreamproject.equals("null")) {
                    upstreamproject = sourceAsMap.get("name") + "";
                }
            } catch (NullPointerException e) {
                System.out.println(sourceAsMap);
                e.printStackTrace();
                continue;
            }
            Object success = sourceAsMap.get("success");
            Map<String, Integer> stringIntegerMap = totalcountmap.get(upstreamproject);
            if (stringIntegerMap == null) {
                HashMap<String, Integer> objectObjectHashMap = new HashMap<>();
                objectObjectHashMap.put("total", 1);
                objectObjectHashMap.put("success", 0);
                totalcountmap.put(upstreamproject, objectObjectHashMap);
            } else {
                Integer total = stringIntegerMap.get("total");
                total += 1;
                Integer tempsuccess = stringIntegerMap.get("success");
                if (success != null) {
                    tempsuccess += 1;
                }
                stringIntegerMap.put("total", total);
                stringIntegerMap.put("success", tempsuccess);
            }
        }
        for (Map.Entry<String, Map<String, Integer>> stringMapEntry : totalcountmap.entrySet()) {
            String key = stringMapEntry.getKey();
            if (key == null) {
                continue;
            }
            Map<String, Integer> value = stringMapEntry.getValue();
            HashMap hashMap = new HashMap();
            hashMap.put("key", key);
            hashMap.put("indic", value);
            long time = System.currentTimeMillis();
            SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss+0800");
            String created_at = simpleDateFormat.format(time);
            created_at = created_at.replace(" ", "T");
            hashMap.put("created_at", created_at);
            Double prob = (value.get("success") / value.get("total").doubleValue()) * 100;
            hashMap.put("prob", prob);
            bulkProcess.add(new IndexRequest(esindex).id(time + key).source(hashMap));
        }
        bulkProcess.flush();
        bulkProcess.close();
        esClient.close();
    }

    @Override
    public void run() {
        try {
            esindex = properties.getProperty(com + "_esindex");
            this.user = properties.getProperty(com + "_name");
            this.password = properties.getProperty(com + "_password");
            gethttpresult(baseurl);

            bulkProcess.flush();
            bulkProcess.close();
        } catch (IOException e) {
            e.printStackTrace();
        } catch (
                Exception e) {
            e.printStackTrace();
            logger.error(e.getMessage(), e);
        } finally {
            if (bulkProcess != null) {
                bulkProcess.close();
            }
            if (esClient != null) {
                try {
                    esClient.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
    }
}


